/*
 * Created on May 4, 2005
 *
 */
package littlecyberwar.ui.overlay;

import java.util.*;
import java.awt.*;

import littlecyberwar.ui.*;
import littlecyberwar.tool.*;
import littlecyberwar.util.*;

/**
 * This is a delegate from the MultiMouseHandler class who handles all the overlay related stuff
 * Have only a single ArrayList that holds all delegates for painting.
 * When one overlay mode is turned on, all existing selected elements need to get added
 * There can only be one overlay turned on at any given time
 * 
 * @author Milton  Soong
 *
 */
public class GlobalOverlayHandler {

	/**
	 * State definition
	 */
	public final static int _ST_INIT=1;		// init state
	public final static int _ST_HAVE_OVERLAY=2;				// Have overlay, no element selected
	public final static int _ST_HAVE_EL_NO_OVERLAY=3;		// have elements selected but no overlay
	public final static int _ST_HAVE_EL_AND_OVERLAY=4;		// have elements selected and have overlay
	
	/**
	 * instance variables 
	 */
	private static int overlayCount;	// total number of choosable overlay types
	private static HashMap delegateMap;	// array of delegate lists, indexed by overlayID
	private static ArrayList elementList;
	private static String overlayId;		// ID of the overlay on (NULL if none selected)
	private static Rectangle rec;
	private static int state;
	
	public GlobalOverlayHandler(int overlayCountIn) {
		super();
		// TODO Auto-generated constructor stub
		overlayCount = overlayCountIn;
		delegateMap = new HashMap(overlayCount);
		state = _ST_INIT;
		
		// !!! DEBUG
		// state = _ST_HAVE_OVERLAY;
		// overlayId = "TEST";
	}
	
	/**
	 * If changed, then if there are already selected elements, then discard them, and then
	 * loop through the elements and then get the delegate from each one.
	 * 
	 * If changed, and there are no selected element, then do nothing.
	 * 
	 * @param idIn the overlayId of the overlay that just got enabled. NULL if it's turned off
	 */
	public void overlayChanged( String idIn ){
		switch ( state ) {
			case _ST_INIT:
				// in this case just change the overlayID and do nothing
				overlayId = idIn;
				break;
				
			case _ST_HAVE_EL_NO_OVERLAY:
			case _ST_HAVE_EL_AND_OVERLAY:
			case _ST_HAVE_OVERLAY:

				// set the id, and then go through each element overlay delegate and then setup the overlayDelegate
				overlayId = idIn;
				createElementOverlayDelegates();
				break;
				
		}
		return;
	}

	/**
	 * Loop through ea 
	 *
	 */
	private void createElementOverlayDelegates() {
		delegateMap = new HashMap();
		for ( int i = 0; i < elementList.size(); i++ ){
			Element el = (Element)elementList.get(i);
			OverlayDelegate ovd = OverlayDelegate.getOverlayDelegateInstance(el, overlayId);
			ovd.elementSelectedWithOverlay(el);
			delegateMap.put(el , ovd);
		}
		return;
	}
	
	public void addElements( ArrayList list ) {
		switch ( state ) {
			case _ST_INIT:
				elementList = list;
				state = _ST_HAVE_EL_NO_OVERLAY;
				break;

			case _ST_HAVE_EL_NO_OVERLAY:
				elementList = list;
				break;
				
			case _ST_HAVE_OVERLAY:
			case _ST_HAVE_EL_AND_OVERLAY:
				// set the id, and then go through each element overlay delegate and then setup the overlayDelegate
				elementList = list;
				createElementOverlayDelegates();
				Rectangle overlayChangedArea = getAreaChanged();
				DirtyAreaManager.addDirtyArea(overlayChangedArea);
				break;
		}
		return;
	}
	/**
	 * if there are no overlay then do nothing. else get the delegate and add it to the ArrayList
	 * 
	 * @param el element that has just been selected
	 */
	public void addElement( Element el ){
		if ( elementList == null ){
			elementList = new ArrayList();
		}
		switch ( state ) {
			case _ST_INIT:
				elementList = new ArrayList();
				elementList.add(el);
				state = _ST_HAVE_EL_NO_OVERLAY;
				break;
				
			case _ST_HAVE_EL_NO_OVERLAY:
				elementList.add(el);
				break;

			case _ST_HAVE_OVERLAY:
			case _ST_HAVE_EL_AND_OVERLAY:
				// set the id, and then go through each element overlay delegate and then setup the overlayDelegate
				elementList.add(el);
				OverlayDelegate ovd = OverlayDelegate.getOverlayDelegateInstance(el, overlayId);
				ovd.elementSelectedWithOverlay(el);
				delegateMap.put(el , ovd);
				
				Rectangle r = ovd.getClearArea();
				if ( r != null ){
					DirtyAreaManager.addDirtyArea(r);
				}
				break;
		}
		return;
	}
	
	/**
	 * remove unit from the arraylist of selected units
	 *  
	 * @param el element that has just been de-selected
	 */
	public void removeElement( Element el ){
		switch ( state ) {
			case _ST_INIT:
			case _ST_HAVE_OVERLAY:
				break;
				
			case _ST_HAVE_EL_NO_OVERLAY:
				elementList.remove(el);
				if ( elementList.size() == 0){
					state = _ST_INIT;
				}
				break;
				
			case _ST_HAVE_EL_AND_OVERLAY:
				// set the id, and then go through each element overlay delegate and then setup the overlayDelegate
				elementList.remove(el);
				delegateMap.remove(el);
				OverlayDelegate od = (OverlayDelegate)delegateMap.get(el);
				if ( od != null ){
					od.elementSelectedWithOverlay(el);
					Rectangle r = od.getClearArea();
					if ( r != null ){
						DirtyAreaManager.addDirtyArea(r);
					}

				} else {
					Debug.out("Something is wrong!");
				}
				break;
		}
		return;
	}
	
	/**
	 * All elements have been removed
	 *
	 */
	public void removeAllElements(){
		switch ( state ) {
			case _ST_INIT:
				break;
				
			case _ST_HAVE_EL_NO_OVERLAY:
			case _ST_HAVE_OVERLAY:

				break;
				
			case _ST_HAVE_EL_AND_OVERLAY:
				// need to build up the clearArea of all the current displaying overlays
				if ( delegateMap.size() > 0 ){
					Collection col = delegateMap.values();
					Iterator i = col.iterator();

					while ( i.hasNext()){
						OverlayDelegate od = (OverlayDelegate)i.next();
						od.elementDeselected();
						Rectangle r = od.getClearArea();
						if ( r != null ){
							DirtyAreaManager.addDirtyArea(r);
						}

					}
				}
				break;
		}

		if ( elementList != null ){
			elementList.clear();
		}
		if ( delegateMap != null ){
			delegateMap.clear();
		}
		return;		
	}
	
	/**
	 * 
	 * @param sel the selectedELementContain of the element that just moved
	 * @return the rectangular area that needs to be repainted
	 */
	public Rectangle unitMoved( SelectedElementContainer sel ){
		Rectangle rec = null;
		return ( rec );
	}
	
	/**
	 * After it's gotten it gets reset
	 * 
	 * @return an rectangular area that has had overlay modified, and need to be repainted 
	 */
	public Rectangle getAreaChanged() {
		Rectangle val = new Rectangle();
		if ( delegateMap.size() > 0 ){
			Collection col = delegateMap.values();
			Iterator i = col.iterator();
			while ( i.hasNext()){
				OverlayDelegate od = (OverlayDelegate)i.next();
				Rectangle r = od.getClearArea();
				if ( r != null ){
					val.add(r);
				}
			}
		}
		return ( val );
	}
	
	public void paintStuff(Graphics2D g2) {
		if ( delegateMap.size() > 0 ){
			Collection col = delegateMap.values();
			Iterator i = col.iterator();
			while ( i.hasNext()){
				OverlayDelegate od = (OverlayDelegate)i.next();
				od.paintStuff(g2);
			}
		}
		return;
	}
}
